<html>
<script>

    // // javaSvaript的面向对象技术

    // // set 集合
    // // 值的任意集合
    // function Set() {
    //     this.value = {};
    //     this.n = 0;
    //     this.add.apply(this, arguments);
    // }

    // // 将每个参数都添加至集合中
    // Set.prototype.add = function () {
    //     for (var i = 0; i < arguments.length; i++) {
    //         var val = arguments[i];
    //         var str = Set._v2s(val);
    //         if (!this.value.hasOwnProperty(str)) {
    //             this.values[str] = val;
    //             this.n++;
    //         }
    //     }
    //     return this;
    // }

    // // 如果集合包含这个值，则返回true；否则返回false
    // Set.prototype.contains = function () {
    //     return this.n;
    // };

    // // 返回集合打大小
    // Set.prototype.size = function () {
    //     return this.size;
    // }

    // // 遍历集合中的所有元素，在指定的上下文中调用f
    // Set.prototype.forEach = function (f, context) {
    //     for (var s in this.values) {
    //         if (this.value.hasOwnProperty(s))
    //             f.call(context, this.value[s]);
    //     }
    // };
    // // 这是一个内部函数，用于将任意JavaScript值和唯一字符串对应起来
    // Set._v2s = function (val) {
    //     switch (val) {
    //         case undefined:
    //             return 'u';
    //         case null:
    //             return 'n';
    //         case true:
    //             return 't';
    //         case false:
    //             return 'f';
    //         default:
    //             switch (key) {
    //                 case 'number': return '#' + val;
    //                 case 'string': return '""' + val;
    //                 default:
    //                     return '@' + Object(val);
    //             }
    //     }
    // }

    // // 对任意字符串来说，都会返回字符串
    // // 针对不同的对象，这个函数会返回不同的字符串
    // // 针对同一个对象的多次使用，总返回相同的字符串
    // // 为了做到这一点，它给o创建了一个属性，在ES5中，这个属性是不可枚举的
    // function ObjectId(o) {
    //     var prop = " |**objectid**| ";
    //     if (!o.hasOwnProperty) {
    //         o[prop] = Set._v2s.next++;  /// 将下一个值赋值给它
    //         return o[prop];
    //     }
    // }
    // Set._v2s.next = 100;    // 设置初始值id的值

    // // 使用4个值创建新的Coin类：Coin.Penny,Coin.Nickel
    // var Coin = enumeration({Penny: 1,Nickel:5,Dime: 10,Quarter:25});
    // var c= Coin.Dime;
    // c instanceof  Coin;
    // c.constructor == Coin
    // Coin.Quarter + 3*Coin.Nickel
    // Coin.Dime == 10;
    // Coin.Dime > Coin.Nickel
    // String(Coin.Dime) + ":" + Coin.Dime;

    // 例子 通过原型继承创建一个新的对象
    function inherit(p) {
        if (p == null) { throw TypeError(); }
        if (Object.create) {

        }
        var t = typeof p;
        if (t !== "object" && t !== "function") { throw TypeError(); }
        function f() { };
        f.prototype = p;
        return new f();
    }

    function enumeration(namesToValues) {
        console.log("start")
        // 这个虚拟的构造函数是返回值
        var enumeration = function () { throw "Can't Instantiate Enumerations" };

        // 枚举值继承自这个属性
        var proto = enumeration.prototype = {
            constructor: enumeration,
            toString: function () { return this.name; },             // 返回名字
            valueOf: function () { return this.value; },             // 返回值
            toJSON: function () { return this.name }
        };

        enumeration.values = [];    // 用以存放枚举对象的数组   

        // 现在创建新类型的实例
        for (name in namesToValues) {
            var e = inherit(proto);
            e.name = name;
            e.value = namesToValues[name];
            enumeration[name] = e;
            // console.log(e);
            // console.log(enumeration.values);
            enumeration.values.push(e);
        }
        console.log(enumeration.values);
        // 一个类方法，用来对类的实例进行迭代
        enumeration.foreach = function (f, c) {
            console.log("this", this.value);
            for (var i = 0; i < this.values.legth; i++) {
                f.call(c, this.value[i]);
            }
        };
        console.log(enumeration);
        // 返回标识这个新类型的构造函数
        return enumeration;
    }

    // 例子 使用枚举类型来表示一副扑克牌
    function Card(suit, rank) {
        this.suit = suit;  // 没张牌都有花色
        this.rank = rank;  // 以及点数
    }

    // 使用枚举类来定义花色和点数
    Card.Suit = enumeration({ clubs: 1, Diamonds: 2, Hearts: 3, Spades: 4 });
    Card.Rank = enumeration({
        Tow: 2, Three: 3, Four: 4, Five: 5, Six: 6,
        Seven: 7, Eight: 8, Nine: 9, Ten: 10, Jack: 11, Queen: 12,
        King: 13, Ace: 14
    });

    // 定义用于描述牌面的文本
    Card.prototype.toString = function (that) {
        return this.rank.toString() + "of" + this.suit.toString()
    }

    // 比较扑克牌中两张牌的大小
    Card.prototype.compareTo = function (that) {
        if (this.rank < that.rank) return -1;
        if (this.rank > that.rank) return 1;
        return 0;
    }

    //以扑克牌的玩法规则进行排序的函数 
    Card.orderByRank = function (a, b) {
        return a.compareTo(b);
    }

    //以桥牌的玩法规则对扑克牌进行排序的函数
    Card.orderBySuit = function (a, b) {
        if (a.suit < b.suit) return -1;
        if (a.suit > b.suit) return 1;
        if (a.rank > b.rank) return -1;
        if (a.rank < b.rank) return;
    }

    // 定义用来表示一副扑克牌的类
    function Deck() {
        var cards = this.cards = [];
        Card.Suit.foreach(function (s) {
            Card.Rank.foreach(function (r) {
                cards.push(new Card(s, r));
            });
        })
    }

    // 洗牌的方法：重新洗牌并返回洗好的牌
    Deck.prototype.shuffle = function () {
        console.log("Deck.prototype.shuffle");
        var deck = this.cards, len = deck.length;
        for (var i = len - 1; i > 0; i--) {
            var r = Math.floor(Math.random() * (i + 1)), temp;    // 随机数
            temp = deck[i], deck[i] = deck[r], deck[r] = temp;   // 交换
        }
        console.log(this);
        return this;
    }

    // 发牌的方法：返回牌的数组
    Deck.prototype.deal = function (n) {
        console.log(this.cards);
        if (this.cards.length < n) throw " Out of cards";
        return this.cards.splice(this.cards.length - n, n);
    }

    var deck = (new Deck()).shuffle();
    console.log(deck);
    var hand = deck.deal(13).sort(Card.orderBySuit);





</script>


<head>
    <title>放置文章标题</title>
</head>

<body>

</body>

</html>